﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Globalization;
//using ASPX;

namespace Xtreme_Server
{
    public class WebServer
    {
        private TcpListener myListener;
        private TcpListener httpsListener;

        public delegate void LogSentEventHandler(object sender, string log);
        public event LogSentEventHandler LogSent;

        private void SendLog(string l)
        {
            LogSent(this, l);

            
            /*LogSentEventHandler temp = LogSent;
            if (temp != null)
            {
                temp(this, l);
            }*/
        }

        public int Port { get; set; }

        public bool EnableHTTPS { get; set; }

        public WebServer()
        {


        }

        public bool Started = false;

        Thread th;

        Thread https_th;

        

        public void Start(int port = 14550)
        {
            try
            {
                SendLog("Starting Xtreme Web Server v0.1...");
                this.Port = port;
                myListener = new TcpListener(Port);
                myListener.Start();

                if (EnableHTTPS)
                {
                    httpsListener = new TcpListener(443);
                    httpsListener.Start();

                    https_th = new Thread(new ThreadStart(HTTPSStartListen));
                    https_th.Start();
                }

                th = new Thread(new ThreadStart(StartListen));
                th.Start();
                SendLog("Server started at port " + Port + ".");
                Started = true;
            }
            catch (Exception e)
            {
                SendLog("An exception occured :" + e.ToString());
            }
        }

        public void Stop()
        {
            try
            {
                SendLog("Stopping Xtreme Web Server v0.1...");

                httpsListener.Stop();



                //th.Dispose();
                https_th.Abort();
                https_th = null;
                Started = false;
                SendLog("Server stopped.");
            }
            catch (Exception e)
            {
                SendLog("An exception occured :" + e.ToString());
            }
        }

        public string GetTheDefaultFileName(string sLocalDirectory)
        {
            StreamReader sr;
            String sLine = "";

            try
            {
                //Open the default.dat to find out the list
                // of default file
                sr = new StreamReader(Path.Combine(Application.StartupPath, @"conf\def.dat"));
                string s = sr.ReadToEnd();
                //MessageBox.Show(s);
                /*foreach (char c in s)
                {
                    MessageBox.Show("" + (byte)c);
                }*/

                /*while ((sLine = sr.ReadLine()) != null)
                {
                    //Look for the default file in the web server root folder
                    if (File.Exists(Path.Combine(sLocalDirectory, sLine)) == true)
                        break;
                }*/
                List<string> def = new List<string>();
                string a = "";
                foreach (char ss in s)
                {
                    if ((byte)ss == 13)
                    {
                        continue;
                    }
                    else if ((byte)ss == 10)
                    {
                        def.Add(a);
                        a = "";
                    }
                    else
                    {
                        a += ss;
                    }
                }
                foreach (string sss in def)
                {
                    string ss1 = sss.Replace("" + (char)10, "");
                    //MessageBox.Show(ss1);
                    //if (File.Exists(Path.Combine(Application.StartupPath, "wwwroot", ss1)) == true)
                    if(File.Exists(Path.Combine(sLocalDirectory, ss1)))
                    {
                        sLine = ss1;
                        //MessageBox.Show(sLine);
                        break;
                    }
                }
            /*abc:

                goto abc;*/
            }
            catch (Exception e)
            {
                SendLog("An exception occurred : " + e.ToString());
            }
            //MessageBox.Show(Path.Combine(Application.StartupPath, "www", sLine));
            if (File.Exists(Path.Combine(Application.StartupPath, "wwwroot", sLine)) == true)
                return sLine;
            else
                return "";
        }

        public string GetLocalPath(string sDirName)
        {

            StreamReader sr;
            String sLine = "";
            String sVirtualDir = "";
            String sRealDir = "";
            int iStartPos = 0;


            sDirName.Trim();



            sDirName = sDirName.ToLower();


            try
            {
                sr = new StreamReader(Path.Combine(Application.StartupPath, @"conf\vfold.dat"));

                while ((sLine = sr.ReadLine()) != null)
                {
                    //sLine.Trim();

                    if (sLine.Length > 0)
                    {
                        iStartPos = sLine.IndexOf(" ");

                        // Convert to lowercase
                        sLine = sLine.ToLower();

                        sVirtualDir = sLine.Substring(0, iStartPos);
                        sRealDir = sLine.Substring(iStartPos + 1);

                        if (sDirName.Length == 1)
                        {
                            if (sVirtualDir == sDirName)
                            {
                                break;
                            }
                        }
                        else
                        {
                            if (sDirName.StartsWith(sVirtualDir))
                            {
                                if (sRealDir.EndsWith("\\"))
                                {
                                    sRealDir += sDirName.Replace('/', '\\').Remove(sDirName.IndexOf('/'), 1);
                                }
                                else
                                {
                                    sRealDir += sDirName.Replace('/', '\\');
                                }
                                //sRealDir = Path.Combine(sRealDir, sDirName.Replace('/', '\\'));
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                SendLog("An Exception Occurred : " + e.ToString());
            }

            if (sRealDir.StartsWith("%%"))
            {
                sRealDir = sRealDir.Substring(3);
                sRealDir = Path.Combine(Application.StartupPath, sRealDir);
            }
            return sRealDir;
            //if (sVirtualDir == sDirName)
            //    return sRealDir;
            //else
            //    return "";
        }

        public string GetMimeType(string sRequestedFile)
        {


            StreamReader sr;
            String sLine = "";
            String sMimeType = "";
            String sFileExt = "";
            String sMimeExt = "";

            // Convert to lowercase
            sRequestedFile = sRequestedFile.ToLower();

            int iStartPos;

            //sFileExt = sRequestedFile.Substring(iStartPos);
            sFileExt = Path.GetExtension(sRequestedFile);

            try
            {
                //Open the Vdirs.dat to find out the list virtual directories
                sr = new StreamReader(Path.Combine(Application.StartupPath, @"conf\mime.dat"));

                while ((sLine = sr.ReadLine()) != null)
                {

                    //sLine.Trim();

                    if (sLine.Length > 0)
                    {
                        //find the separator
                        iStartPos = sLine.IndexOf(" ");

                        // Convert to lower case
                        sLine = sLine.ToLower();

                        sMimeExt = sLine.Substring(0, iStartPos);
                        sMimeType = sLine.Substring(iStartPos + 1);

                        if (sMimeExt == sFileExt)
                            break;
                    }
                }
            }
            catch (Exception e)
            {
                SendLog("An exception occurred : " + e.ToString());
            }

            if (sMimeExt == sFileExt)
                return sMimeType;
            else
                return "";
        }

        public void SendHeader(string sHttpVersion, string sMIMEHeader,
            int iTotBytes, string sStatusCode, ref Socket mySocket)
        {

            String sBuffer = "";

            // if Mime type is not provided set default to text/html
            if (sMIMEHeader.Length == 0)
            {
                sMIMEHeader = "text/html";  // Default Mime Type is text/html
            }

            sBuffer = sBuffer + sHttpVersion + sStatusCode + "\r\n";
            sBuffer = sBuffer + "Server: cx1193719-b\r\n";
            sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n";
            sBuffer = sBuffer + "Accept-Ranges: bytes\r\n";
            sBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n";

            Byte[] bSendData = Encoding.ASCII.GetBytes(sBuffer);

            SendToBrowser(bSendData, ref mySocket);

            SendLog("Total Bytes : " + iTotBytes.ToString());

        }

        public void SendToBrowser(String sData, ref Socket mySocket)
        {
            SendToBrowser(Encoding.ASCII.GetBytes(sData), ref mySocket);
        }


        public void SendToBrowser(Byte[] bSendData, ref Socket mySocket)
        {
            int numBytes = 0;
            try
            {
                if (mySocket.Connected)
                {
                    if ((numBytes = mySocket.Send(bSendData, bSendData.Length, 0)) == -1)
                        SendLog("Socket Error! Cannot send packet");
                    else
                    {
                        SendLog("Bytes send : " + numBytes);
                    }
                }
                else
                    SendLog("Connection lost.");
            }
            catch (Exception e)
            {
                SendLog("An error occurred : " + e);
            }
        }

        public int ClientsCount { get { return this._clientscount; } }
        private int _clientscount;

        public int MaxClient { get; set; }

        public void StartListen()
        {

            int iStartPos = 0;
            String sRequest;
            String sDirName;
            String sRequestedFile = "";
            String sErrorMessage;
            String sLocalDir;
            String sPhysicalFilePath = "";
            String sFormattedMessage = "";
            String sResponse = "";


            while (true)
            {
                //Accept a new connection
                //myListener.
                Socket mySocket = myListener.AcceptSocket();

                SendLog("Socket type : " + mySocket.SocketType);
                if (mySocket.Connected)
                {
                    if (ClientsCount == MaxClient)
                    {
                        mySocket.Disconnect(false);
                        return;
                    }
                    SendLog("Client Connected.\r\n==================\r\nClient IP : " + mySocket.RemoteEndPoint);
                    _clientscount++;


                    //make a byte array and receive data from the client 
                    Byte[] bReceive = new Byte[1024];
                    int i = mySocket.Receive(bReceive, bReceive.Length, 0);

                    string QUERY_STRING = "";

                    


                    //Convert Byte to String
                    string sBuffer = Encoding.ASCII.GetString(bReceive);

                    string Host = "";
                    string UserAgent = "";
                    string Referer = "";

                    foreach (string s in sBuffer.Split('\n'))
                    {
                        if(s.StartsWith("Host: "))
                        {
                            Host = s.Replace("Host: ", "");
                        }
                        else if (s.StartsWith("User-Agent: "))
                        {
                            UserAgent = s.Replace("User-Agent: ", "");
                        }
                        else if (s.StartsWith("Referer: "))
                        {
                            Referer = s.Replace("Referer: ", "");
                        }
                    }


                    //At present we will only deal with GET type
                    /*if (sBuffer.Substring(0, 3) != "GET")
                    {
                        SendLog("Only 'GET' method is supported.");
                        mySocket.Close();
                        return;
                    }*/

                    string[] param = sBuffer.Split(new char[] { '\n' });

                    // Look for HTTP request
                    iStartPos = sBuffer.IndexOf("HTTP", 1);

                    try
                    {
sRequest = sBuffer.Substring(0, iStartPos - 1);
                    }
                    catch (Exception)
                    {
                        continue;
                        return;
                    }

                    
                    // Get the HTTP text and version e.g. it will return "HTTP/1.1"
                    string sHttpVersion = sBuffer.Substring(iStartPos, 8);

                    if (sBuffer.Substring(0, 3) == "GET")
                    {
                        sRequestedFile = sRequest.Replace("/", "\\");//.Trim();
                        if (sRequestedFile.Contains("?"))
                        {
                            string v = sRequestedFile;
                            sRequestedFile = sRequestedFile.Replace(sRequestedFile.Substring(sRequestedFile.IndexOf('?')), "");

                            /*foreach (string x in param)
                            {
                                if (x.StartsWith("Referer: "))
                                {
                                    
                                }
                            } */
                            /*string x = sRequest;
                            string z1 = x.Substring(4);
                            //string z2 = z1.Substring(z1.IndexOf('/'));
                            //string z3 = z2.Substring(z2.IndexOf('/'));
                            //string z4 = z3.Substring(z3.IndexOf('/'));
                            int xxx = z1.LastIndexOf('/');
                            string z4 = z1.Substring(xxx + 1);
                            string z5 = z4.Replace(sRequestedFile, "").Substring(1).Replace("\r", "");*/
                            //QUERY_STRING = sRequest/*edFile*/.Substring(sRequest/*edFile*/.IndexOf('?') + 1);
                            QUERY_STRING = sRequestedFile.Substring(v.IndexOf('?'));
                        }
                        //QUERY_STRING = params(params.Length - 1).Trim();
                    }
                    else if (sBuffer.Substring(0, 4) == "POST")
                    {
                        sRequestedFile = sRequest.Replace("/", "\\");//.Trim();
                        
                        QUERY_STRING = param[param.Length - 1].Trim();
                    }
                    else if (sBuffer.Substring(0, 4) == "HEAD")
                    {
                        break;
                    }
                    else
                    {
                        sRequestedFile = "";
                        SendHeader(sHttpVersion, "", File.ReadAllText(Path.Combine(Application.StartupPath, "pages", "errors", "BadRequest.htm")).Length, "400 Bad Request", ref mySocket);
                        //SendHeader(sHttpVersion, "", File.ReadAllText(Path.Combine(Application.StartupPath, "pages", "errors", "BadRequest.htm")).Length, "400 
                        SendToBrowser(File.ReadAllText(Path.Combine(Application.StartupPath, "pages", "errors", "BadRequest.htm")), ref mySocket);
                        mySocket.Close();
                        return;
                        break;
                        return;
                    }


                    // Extract the Requested Type and Requested file/directory
                    


                    //Replace backslash with Forward Slash, if Any
                    //sRequest.Replace("\\", "/");


                    //If file name is not supplied add forward slash to indicate 
                    //that it is a directory and then we will look for the 
                    //default file name..
                    if ((sRequest.IndexOf(".") < 1) && (!sRequest.EndsWith("/")))
                    {
                        sRequest = sRequest + "/";
                    }
                    //Extract the requested file name
                    iStartPos = sRequest.LastIndexOf("/") + 1;
                    sRequestedFile = sRequest.Substring(iStartPos);


                    //Extract The directory Name
                    int s1s = sRequest.IndexOf("/");
                    int s2s = sRequest.LastIndexOf("/");
                    s2s = s2s - 3;

                    string sab = sRequest;

                    if (sab.StartsWith(@"GET \"))
                    {
                        int ab = sab.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('\\') + 1);
                    }
                    else if (sab.StartsWith(@"GET /"))
                    {
                        int ab = sab.LastIndexOf('/');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('/') + 1);
                    }
                    else if (sab.StartsWith(@"POST \"))
                    {
                        int ab = sab.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('\\') + 1);
                    }
                    else if (sab.StartsWith(@"POST /"))
                    {
                        int ab = sab.LastIndexOf('/');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('/') + 1);
                    }

                    sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/") - 3);
                    //sDirName = sRequest.Substring(sRequest.IndexOf("/"));
                    /////////////////////////////////////////////////////////////////////
                    // Identify the Physical Directory
                    /////////////////////////////////////////////////////////////////////
                    //if (sDirName == "/")
                    //    sLocalDir = sMyWebServerRoot;
                    //else
                    //{
                        //Get the Virtual Directory
                        sLocalDir = GetLocalPath(sDirName);
                    //}


                    SendLog("Directory requested : " + sLocalDir);

                    if (sRequestedFile.StartsWith(@"GET \"))
                    {
                        int ab = sRequestedFile.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sRequestedFile = sRequestedFile.Substring(sRequestedFile.LastIndexOf('\\') + 1);
                    }
                    else if (sRequestedFile.StartsWith(@"POST \"))
                    {
                        int ab = sRequestedFile.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sRequestedFile = sRequestedFile.Substring(sRequestedFile.LastIndexOf('\\') + 1);
                    }

                    //If the physical directory does not exists then
                    // dispaly the error message
                    if (sLocalDir.Length == 0)
                    {
                        //sErrorMessage = "<H2>Error!! Requested Directory does not exists</H2><Br>";
                        sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\Error404.htm"));
                        //sErrorMessage = sErrorMessage + "Please check data\\Vdirs.Dat";

                        //Format The Message
                        SendHeader(sHttpVersion, "", sErrorMessage.Length,
                                   " 404 Not Found", ref mySocket);

                        //Send to the browser
                        SendToBrowser(sErrorMessage, ref mySocket);

                        mySocket.Close();

                        continue;
                    }
                    /////////////////////////////////////////////////////////////////////
                    // Identify the File Name
                    /////////////////////////////////////////////////////////////////////

                    //If The file name is not supplied then look in the default file list
                    if (sRequestedFile.Length == 0)
                    {
                        // Get the default filename
                        sRequestedFile = GetTheDefaultFileName(sLocalDir);

                        if (sRequestedFile == "")
                        {
                            if (FolderConfigFile.FromFolder(sLocalDir).AllowListing)
                            {
                                sErrorMessage = GetListing(sLocalDir);
                                SendHeader(sHttpVersion, "", sErrorMessage.Length,
                                           " 200 OK", ref mySocket);
                                SendToBrowser(sErrorMessage, ref mySocket);
                            }
                            else
                            {
                                sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\NoDefPage.htm"));
                                SendHeader(sHttpVersion, "", sErrorMessage.Length,
                                           " 404 Not Found", ref mySocket);
                                SendToBrowser(sErrorMessage, ref mySocket);
                            }

                            mySocket.Close();

                            return;

                        }
                    }

                    //sRequestedFile = sRequestedFile.Replace(sRequestedFile.Substring(sRequestedFile.IndexOf('?')), "");

                    //////////////////////////////////////////////////
                    // Get TheMime Type
                    //////////////////////////////////////////////////

                    if (sRequestedFile.Contains("?"))
                    {
                        sRequestedFile = sRequestedFile.Replace(sRequestedFile.Substring(sRequestedFile.IndexOf('?')), "");

                    }

                    String sMimeType = GetMimeType(sRequestedFile);


                    //Build the physical path
                    
                    sPhysicalFilePath = Path.Combine(sLocalDir, sRequestedFile);
                    SendLog("File requested : " + sPhysicalFilePath);
                    if (File.Exists(sPhysicalFilePath) == false)
                    {
                        
                        if (Path.GetFileName(sPhysicalFilePath) != "favicon.ico")
                        {
                            sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\Error404.htm"));
                            SendHeader(sHttpVersion, "", sErrorMessage.Length,
                                       " 404 Not Found", ref mySocket);
                            SendToBrowser(sErrorMessage, ref mySocket);

                            SendLog(sFormattedMessage);
                        }
                    }
                    else
                    {
                        int iTotBytes = 0;

                        sResponse = "";

                        FileStream fs = new FileStream(sPhysicalFilePath,
                                        FileMode.Open, FileAccess.Read,
                          FileShare.Read);

                        string ext = new FileInfo(sPhysicalFilePath).Extension.ToLower();

                        ext = ext.Replace(".", "");

                        if (ext == "aspx")
                        {
                            /*ASPClass aspxHost = new ASPClass();
                            //Pass the filename to it and return the html output
                            string htmlOut = aspxHost.CreateHost(requestedFile, serverRoot);
                            erMesLen = htmlOut.Length;
                            SendHeader(SERVER_PROTOCOL, mimeType, erMesLen, " 200 OK", sockets);
                            SendData(htmlOut, sockets);*/
                        }
                        else if (ext == "php" || ext == "php3" || ext == "php4" || ext == "php5" || ext == "phtml")
                        {
                            //BinaryReader reader1 = new BinaryReader(fs);
                            //byte[] bytes1 = new byte[fs.Length];
                            //int read1;
                            //while ((read1 = reader1.Read(bytes1, 0, bytes1.Length)) != 0)
                            //{
                            string phpabccgi = GetCgiData(sPhysicalFilePath, QUERY_STRING, ext, mySocket.RemoteEndPoint.ToString(), sHttpVersion, Referer, "", UserAgent, QUERY_STRING/*, !sRequest.StartsWith("GET")*/);
                                // Read from the file and write the data to the network
                                //byte[] bytes1_1 = Encoding.ASCII.GetBytes(phpabccgi);

                                //sResponse = sResponse + Encoding.ASCII.GetString(bytes1_1);
                            //sResponse += phpabccgi;

                            //iTotBytes = iTotBytes + read1;

                            //}
                            //reader1.Close();
                            //fs.Close();

                            //phpabccgi = phpabccgi.Substring(3);

                            iTotBytes = phpabccgi.Length;

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(Encoding.ASCII.GetBytes(phpabccgi), ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }
                        else if (ext == "ssc")
                        {
                            //BinaryReader reader1 = new BinaryReader(fs);
                            //byte[] bytes1 = new byte[fs.Length];
                            //int read1;
                            //while ((read1 = reader1.Read(bytes1, 0, bytes1.Length)) != 0)
                            //{
                            string phpabccgi = GetSplitSharpData(sPhysicalFilePath);
                            // Read from the file and write the data to the network
                            //byte[] bytes1_1 = Encoding.ASCII.GetBytes(phpabccgi);

                            //sResponse = sResponse + Encoding.ASCII.GetString(bytes1_1);
                            //sResponse += phpabccgi;

                            //iTotBytes = iTotBytes + read1;

                            //}
                            //reader1.Close();
                            //fs.Close();

                            //phpabccgi = phpabccgi.Substring(3);

                            iTotBytes = phpabccgi.Length;

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(Encoding.ASCII.GetBytes(phpabccgi), ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }
                        else if (ext == "py" || ext == "pyc" || ext == "pyo" || ext == "pyw")
                        {
                            
                            string phpabccgi = GetPythonData(sPhysicalFilePath);
                            

                            iTotBytes = phpabccgi.Length;

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(Encoding.ASCII.GetBytes(phpabccgi), ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }
                        else
                        {

                            BinaryReader reader = new BinaryReader(fs);
                            byte[] bytes = new byte[fs.Length];
                            int read;
                            while ((read = reader.Read(bytes, 0, bytes.Length)) != 0)
                            {
                                // Read from the file and write the data to the network
                                sResponse = sResponse + Encoding.ASCII.GetString(bytes, 0, read);

                                iTotBytes = iTotBytes + read;

                            }
                            reader.Close();
                            fs.Close();

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(bytes, ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }

                    }
                    mySocket.Close();
                }

            }

        }

        public void HTTPSStartListen()
        {

            int iStartPos = 0;
            String sRequest;
            String sDirName;
            String sRequestedFile = "";
            String sErrorMessage;
            String sLocalDir;
            String sPhysicalFilePath = "";
            String sFormattedMessage = "";
            String sResponse = "";


            while (true)
            {
                //Accept a new connection
                //myListener.
                Socket mySocket = myListener.AcceptSocket();

                SendLog("Socket type : " + mySocket.SocketType);
                if (mySocket.Connected)
                {
                    if (ClientsCount == MaxClient)
                    {
                        mySocket.Disconnect(false);
                        return;
                    }
                    SendLog("Client Connected.\r\n==================\r\nClient IP : " + mySocket.RemoteEndPoint);
                    _clientscount++;


                    //make a byte array and receive data from the client 
                    Byte[] bReceive = new Byte[1024];
                    int i = mySocket.Receive(bReceive, bReceive.Length, 0);

                    string QUERY_STRING = "";




                    //Convert Byte to String
                    string sBuffer = Encoding.ASCII.GetString(bReceive);

                    string Host = "";
                    string UserAgent = "";
                    string Referer = "";

                    foreach (string s in sBuffer.Split('\n'))
                    {
                        if (s.StartsWith("Host: "))
                        {
                            Host = s.Replace("Host: ", "");
                        }
                        else if (s.StartsWith("User-Agent: "))
                        {
                            UserAgent = s.Replace("User-Agent: ", "");
                        }
                        else if (s.StartsWith("Referer: "))
                        {
                            Referer = s.Replace("Referer: ", "");
                        }
                    }


                    //At present we will only deal with GET type
                    /*if (sBuffer.Substring(0, 3) != "GET")
                    {
                        SendLog("Only 'GET' method is supported.");
                        mySocket.Close();
                        return;
                    }*/

                    string[] param = sBuffer.Split(new char[] { '\n' });

                    // Look for HTTP request
                    iStartPos = sBuffer.IndexOf("HTTP", 1);

                    try
                    {
                        sRequest = sBuffer.Substring(0, iStartPos - 1);
                    }
                    catch (Exception)
                    {
                        continue;
                        return;
                    }


                    // Get the HTTP text and version e.g. it will return "HTTP/1.1"
                    string sHttpVersion = sBuffer.Substring(iStartPos, 8);

                    if (sBuffer.Substring(0, 3) == "GET")
                    {
                        sRequestedFile = sRequest.Replace("/", "\\");//.Trim();
                        if (sRequestedFile.Contains("?"))
                        {
                            sRequestedFile = sRequestedFile.Replace(sRequestedFile.Substring(sRequestedFile.IndexOf('?')), "");

                            QUERY_STRING = sRequest/*edFile*/.Substring(sRequest/*edFile*/.IndexOf('?') + 1);
                        }
                        //QUERY_STRING = params(params.Length - 1).Trim();
                    }
                    else if (sBuffer.Substring(0, 4) == "POST")
                    {
                        sRequestedFile = sRequest.Replace("/", "\\");//.Trim();
                        QUERY_STRING = param[param.Length - 1].Trim();
                    }
                    else if (sBuffer.Substring(0, 4) == "HEAD")
                    {
                        break;
                    }
                    else
                    {
                        sRequestedFile = "";
                        SendHeader(sHttpVersion, "", File.ReadAllText(Path.Combine(Application.StartupPath, "pages", "errors", "BadRequest.htm")).Length, "400 Bad Request", ref mySocket);
                        //SendHeader(sHttpVersion, "", File.ReadAllText(Path.Combine(Application.StartupPath, "pages", "errors", "BadRequest.htm")).Length, "400 
                        SendToBrowser(File.ReadAllText(Path.Combine(Application.StartupPath, "pages", "errors", "BadRequest.htm")), ref mySocket);
                        mySocket.Close();
                        return;
                        break;
                        return;
                    }


                    // Extract the Requested Type and Requested file/directory



                    //Replace backslash with Forward Slash, if Any
                    //sRequest.Replace("\\", "/");


                    //If file name is not supplied add forward slash to indicate 
                    //that it is a directory and then we will look for the 
                    //default file name..
                    if ((sRequest.IndexOf(".") < 1) && (!sRequest.EndsWith("/")))
                    {
                        sRequest = sRequest + "/";
                    }
                    //Extract the requested file name
                    iStartPos = sRequest.LastIndexOf("/") + 1;
                    sRequestedFile = sRequest.Substring(iStartPos);


                    //Extract The directory Name
                    int s1s = sRequest.IndexOf("/");
                    int s2s = sRequest.LastIndexOf("/");
                    s2s = s2s - 3;

                    string sab = sRequest;

                    if (sab.StartsWith(@"GET \"))
                    {
                        int ab = sab.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('\\') + 1);
                    }
                    else if (sab.StartsWith(@"GET /"))
                    {
                        int ab = sab.LastIndexOf('/');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('/') + 1);
                    }
                    else if (sab.StartsWith(@"POST \"))
                    {
                        int ab = sab.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('\\') + 1);
                    }
                    else if (sab.StartsWith(@"POST /"))
                    {
                        int ab = sab.LastIndexOf('/');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sab = sab.Substring(sab.LastIndexOf('/') + 1);
                    }

                    sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/") - 3);
                    //sDirName = sRequest.Substring(sRequest.IndexOf("/"));
                    /////////////////////////////////////////////////////////////////////
                    // Identify the Physical Directory
                    /////////////////////////////////////////////////////////////////////
                    //if (sDirName == "/")
                    //    sLocalDir = sMyWebServerRoot;
                    //else
                    //{
                    //Get the Virtual Directory
                    sLocalDir = GetLocalPath(sDirName);
                    //}


                    SendLog("Directory requested : " + sLocalDir);

                    if (sRequestedFile.StartsWith(@"GET \"))
                    {
                        int ab = sRequestedFile.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sRequestedFile = sRequestedFile.Substring(sRequestedFile.LastIndexOf('\\') + 1);
                    }
                    else if (sRequestedFile.StartsWith(@"POST \"))
                    {
                        int ab = sRequestedFile.LastIndexOf('\\');
                        bool b;
                        /*for (int j = 0; j < sRequestedFile.Length; j++)
                        {
                        }*/
                        sRequestedFile = sRequestedFile.Substring(sRequestedFile.LastIndexOf('\\') + 1);
                    }

                    //If the physical directory does not exists then
                    // dispaly the error message
                    if (sLocalDir.Length == 0)
                    {
                        //sErrorMessage = "<H2>Error!! Requested Directory does not exists</H2><Br>";
                        sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\Error404.htm"));
                        //sErrorMessage = sErrorMessage + "Please check data\\Vdirs.Dat";

                        //Format The Message
                        SendHeader(sHttpVersion, "", sErrorMessage.Length,
                                   " 404 Not Found", ref mySocket);

                        //Send to the browser
                        SendToBrowser(sErrorMessage, ref mySocket);

                        mySocket.Close();

                        continue;
                    }
                    /////////////////////////////////////////////////////////////////////
                    // Identify the File Name
                    /////////////////////////////////////////////////////////////////////

                    //If The file name is not supplied then look in the default file list
                    if (sRequestedFile.Length == 0)
                    {
                        // Get the default filename
                        sRequestedFile = GetTheDefaultFileName(sLocalDir);

                        if (sRequestedFile == "")
                        {
                            if (FolderConfigFile.FromFolder(sLocalDir).AllowListing)
                            {
                                SendHeader(sHttpVersion, "text/html", System.Text.Encoding.UTF8.GetBytes(GetListing(sLocalDir)).Length, " 200 OK", ref mySocket);
                                //bytes = Encoding.ASCII.GetBytes(bytes);
                                SendToBrowser(GetListing(sLocalDir), ref mySocket);
                            }
                            else
                            {
                                sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\NoDefPage.htm"));
                                SendHeader(sHttpVersion, "", sErrorMessage.Length,
                                           " 404 Not Found", ref mySocket);
                                SendToBrowser(sErrorMessage, ref mySocket);
                            }

                            mySocket.Close();

                            return;

                        }
                    }

                    //sRequestedFile = sRequestedFile.Replace(sRequestedFile.Substring(sRequestedFile.IndexOf('?')), "");

                    //////////////////////////////////////////////////
                    // Get TheMime Type
                    //////////////////////////////////////////////////

                    if (sRequestedFile.Contains("?"))
                    {
                        sRequestedFile = sRequestedFile.Replace(sRequestedFile.Substring(sRequestedFile.IndexOf('?')), "");

                    }

                    String sMimeType = GetMimeType(sRequestedFile);


                    //Build the physical path

                    sPhysicalFilePath = Path.Combine(sLocalDir, sRequestedFile);
                    SendLog("File requested : " + sPhysicalFilePath);
                    if (File.Exists(sPhysicalFilePath) == false)
                    {

                        if (Path.GetFileName(sPhysicalFilePath) != "favicon.ico")
                        {
                            sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\Error404.htm"));
                            SendHeader(sHttpVersion, "", sErrorMessage.Length,
                                       " 404 Not Found", ref mySocket);
                            SendToBrowser(sErrorMessage, ref mySocket);

                            SendLog(sFormattedMessage);
                        }
                    }
                    else
                    {
                        int iTotBytes = 0;

                        sResponse = "";

                        FileStream fs = new FileStream(sPhysicalFilePath,
                                        FileMode.Open, FileAccess.Read,
                          FileShare.Read);

                        string ext = new FileInfo(sPhysicalFilePath).Extension.ToLower();

                        ext = ext.Replace(".", "");

                        if (ext == "aspx")
                        {
                            /*ASPClass aspxHost = new ASPClass();
                            //Pass the filename to it and return the html output
                            string htmlOut = aspxHost.CreateHost(requestedFile, serverRoot);
                            erMesLen = htmlOut.Length;
                            SendHeader(SERVER_PROTOCOL, mimeType, erMesLen, " 200 OK", sockets);
                            SendData(htmlOut, sockets);*/
                        }
                        else if (ext == "php" || ext == "php3" || ext == "php4" || ext == "php5" || ext == "phtml")
                        {
                            //BinaryReader reader1 = new BinaryReader(fs);
                            //byte[] bytes1 = new byte[fs.Length];
                            //int read1;
                            //while ((read1 = reader1.Read(bytes1, 0, bytes1.Length)) != 0)
                            //{
                            string phpabccgi = GetCgiData(sPhysicalFilePath, QUERY_STRING, ext, mySocket.RemoteEndPoint.ToString(), sHttpVersion, Referer, "", UserAgent, ""/*, !sRequest.StartsWith("GET")*/);
                            // Read from the file and write the data to the network
                            //byte[] bytes1_1 = Encoding.ASCII.GetBytes(phpabccgi);

                            //sResponse = sResponse + Encoding.ASCII.GetString(bytes1_1);
                            //sResponse += phpabccgi;

                            //iTotBytes = iTotBytes + read1;

                            //}
                            //reader1.Close();
                            //fs.Close();

                            //phpabccgi = phpabccgi.Substring(3);

                            iTotBytes = phpabccgi.Length;

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(Encoding.ASCII.GetBytes(phpabccgi), ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }
                        else if (ext == "ssc")
                        {
                            //BinaryReader reader1 = new BinaryReader(fs);
                            //byte[] bytes1 = new byte[fs.Length];
                            //int read1;
                            //while ((read1 = reader1.Read(bytes1, 0, bytes1.Length)) != 0)
                            //{
                            string phpabccgi = GetSplitSharpData(sPhysicalFilePath);
                            // Read from the file and write the data to the network
                            //byte[] bytes1_1 = Encoding.ASCII.GetBytes(phpabccgi);

                            //sResponse = sResponse + Encoding.ASCII.GetString(bytes1_1);
                            //sResponse += phpabccgi;

                            //iTotBytes = iTotBytes + read1;

                            //}
                            //reader1.Close();
                            //fs.Close();

                            //phpabccgi = phpabccgi.Substring(3);

                            iTotBytes = phpabccgi.Length;

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(Encoding.ASCII.GetBytes(phpabccgi), ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }
                        else if (ext == "py" || ext == "pyc" || ext == "pyo" || ext == "pyw")
                        {

                            string phpabccgi = GetPythonData(sPhysicalFilePath);


                            iTotBytes = phpabccgi.Length;

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(Encoding.ASCII.GetBytes(phpabccgi), ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }
                        else
                        {

                            BinaryReader reader = new BinaryReader(fs);
                            byte[] bytes = new byte[fs.Length];
                            int read;
                            while ((read = reader.Read(bytes, 0, bytes.Length)) != 0)
                            {
                                // Read from the file and write the data to the network
                                sResponse = sResponse + Encoding.ASCII.GetString(bytes, 0, read);

                                iTotBytes = iTotBytes + read;

                            }
                            reader.Close();
                            fs.Close();

                            SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                            //bytes = Encoding.ASCII.GetBytes(bytes);
                            SendToBrowser(bytes, ref mySocket);
                            //mySocket.Send(bytes, bytes.Length,0);
                        }

                    }
                    mySocket.Close();
                }

            }

        }

        /*private string GetCgiData(string cgiFile, string QUERY_STRING, string ext, string remote_address, string SERVER_PROTOCOL, string REFERER, string REQUESTED_METHOD, string USER_AGENT, string request, bool POST)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            //indicate the executable to get stdout
            if (ext == "php" || ext == ".php")
            {
                proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "php", "php-cgi.exe");
                //proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "php", "php.exe");
                //if path to the php is not defined
                if (!File.Exists(proc.StartInfo.FileName))
                {
                    string sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\MissingPHP.htm"));
                    //SendHeader(sHttpVersion, "", sErrorMessage.Length,
                    //           " 404 Not Found", ref mySocket);
                    //(sErrorMessage, ref mySocket);
                    return sErrorMessage;

                    //SendLog(sFormattedMessage);
                }
                //proc.StartInfo.Arguments =   /*" -q " + cgiFile + " " + QUERY_STRING;
                /*if (!POST)
                {
                    proc.StartInfo.Arguments += "DO.NOT.DELETE.php ";
                }
                else
                {
                    proc.StartInfo.Arguments += "DO.NOT.DELETE.POST.php ";
                }
                proc.StartInfo.Arguments += '"';
                proc.StartInfo.Arguments += cgiFile;
                if (QUERY_STRING != null || !string.IsNullOrEmpty(QUERY_STRING) || string.IsNullOrWhiteSpace(QUERY_STRING))
                {
                    proc.StartInfo.Arguments += "?" + QUERY_STRING;
                }
                proc.StartInfo.Arguments += '"';
                //proc.StartInfo.Arguments += " ";

                /*if (QUERY_STRING.Contains("&"))
                {
                    string[] xv = QUERY_STRING.Split('&');
                    foreach (string a in xv)
                    {

                    }
                }
                //string a = QUERY_STRING.Replace("&", " ");
                //proc.StartInfo.Arguments += QUERY_STRING;
            }
            else
            {
                proc.StartInfo.FileName = cgiFile;
                proc.StartInfo.Arguments = QUERY_STRING;
            }
            string script_name = cgiFile.Substring(cgiFile.LastIndexOf('\\') + 1);
            //Set some global variables and output parameters
            proc.StartInfo.EnvironmentVariables.Add("REMOTE_ADDR", remote_address.ToString());
            proc.StartInfo.EnvironmentVariables.Add("SCRIPT_NAME", script_name);
            proc.StartInfo.EnvironmentVariables.Add("SCRIPT_FILENAME", script_name);
            proc.StartInfo.EnvironmentVariables.Add("USER_AGENT", USER_AGENT);
            proc.StartInfo.EnvironmentVariables.Add("REQUESTED_METHOD", REQUESTED_METHOD);
            proc.StartInfo.EnvironmentVariables.Add("REFERER", REFERER);
            proc.StartInfo.EnvironmentVariables.Add("SERVER_PROTOCOL", SERVER_PROTOCOL);
            proc.StartInfo.EnvironmentVariables.Add("QUERY_STRING", request);
            proc.StartInfo.EnvironmentVariables.Add("SERVER", "Xtreme Web Server 0.1");
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.CreateNoWindow = true;
            string str = "";
            proc.Start();
            
            str = proc.StandardOutput.ReadToEnd();
            proc.Close();
            proc.Dispose();
            return str;
        }*/

        /// <summary>
        /// The method to Decode your Base64 strings.
        /// </summary>
        /// <param name="encodedData">The String containing the characters to decode.</param>
        /// <returns>A String containing the results of decoding the specified sequence of bytes.</returns>
        public static string DecodeFrom64(string encodedData)
        {

            byte[] encodedDataAsBytes

                = System.Convert.FromBase64String(encodedData);

            string returnValue =

               System.Text.Encoding.Unicode.GetString(encodedDataAsBytes);

            return returnValue;

        }

        private string GetCgiData(string cgiFile, string QUERY_STRING, string ext, string remote_address, string SERVER_PROTOCOL, string REFERER, string REQUESTED_METHOD, string USER_AGENT, string request)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            //indicate the executable to get stdout
            if (ext == "php" || ext == ".php")
            {
                //proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "php", "php-cgi.exe");
                proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "php", "php-cgi.exe");
                //if path to the php is not defined
                if (!File.Exists(proc.StartInfo.FileName))
                {
                    string sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\MissingPHP.htm"));
                    //SendHeader(sHttpVersion, "", sErrorMessage.Length,
                    //           " 404 Not Found", ref mySocket);
                    //(sErrorMessage, ref mySocket);
                    return sErrorMessage;

                    //SendLog(sFormattedMessage);
                }
                //proc.StartInfo.Arguments =   /*" -q " + */cgiFile + " " + QUERY_STRING;
                proc.StartInfo.Arguments += '"';
                proc.StartInfo.Arguments += cgiFile;
                proc.StartInfo.Arguments += '"';

            }
            else
            {
                proc.StartInfo.FileName = cgiFile;
                proc.StartInfo.Arguments = QUERY_STRING;
            }
            string script_name = cgiFile.Substring(cgiFile.LastIndexOf('\\') + 1);
            //Set some global variables and output parameters
            proc.StartInfo.EnvironmentVariables.Add("REMOTE_ADDR", remote_address.ToString());
            proc.StartInfo.EnvironmentVariables.Add("SCRIPT_NAME", script_name);
            proc.StartInfo.EnvironmentVariables.Add("SCRIPT_FILENAME", script_name);
            proc.StartInfo.EnvironmentVariables.Add("USER_AGENT", USER_AGENT);
            proc.StartInfo.EnvironmentVariables.Add("REQUESTED_METHOD", REQUESTED_METHOD);
            proc.StartInfo.EnvironmentVariables.Add("REFERER", REFERER);
            proc.StartInfo.EnvironmentVariables.Add("SERVER_PROTOCOL", SERVER_PROTOCOL);
            proc.StartInfo.EnvironmentVariables.Add("QUERY_STRING", request);
            proc.StartInfo.EnvironmentVariables.Add("SERVER", "Xtreme Web Server 0.1");
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.CreateNoWindow = true;
            string str = "";
            proc.Start();
            
            str = proc.StandardOutput.ReadToEnd();
            proc.Close();
            proc.Dispose();
            return str;
        }


        private string GetSplitSharpData(string cgiFile)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            System.Diagnostics.Process proc1 = new System.Diagnostics.Process();

            string name = Path.GetFileNameWithoutExtension(cgiFile);
            //indicate the executable to get stdout
            
            proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "splitsharp", "viper.exe");
            proc1.StartInfo.FileName = Path.Combine(Application.StartupPath, "splitsharp", "ssc.exe");
            //if path to the php is not defined
            if (!File.Exists(proc.StartInfo.FileName) || !File.Exists(proc1.StartInfo.FileName))
            {
                string sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\MissingSplitSharp.htm"));
                //SendHeader(sHttpVersion, "", sErrorMessage.Length,
                //           " 404 Not Found", ref mySocket);
                //(sErrorMessage, ref mySocket);
                return sErrorMessage;

                //SendLog(sFormattedMessage);
            }
            //proc.StartInfo.Arguments =   /*" -q " + */cgiFile + " " + QUERY_STRING;
            proc1.StartInfo.Arguments += '"';
            proc1.StartInfo.Arguments += cgiFile;
            proc1.StartInfo.Arguments += '"';
            proc1.StartInfo.Arguments += " ";
            proc1.StartInfo.Arguments += "-o ";
            proc1.StartInfo.Arguments += '"';
            proc1.StartInfo.Arguments += Path.Combine(cgiFile.Replace(Path.GetFileName(cgiFile), ""), name + ".gex");
            proc1.StartInfo.Arguments += '"';

           
           
            proc1.StartInfo.UseShellExecute = false;
            proc1.StartInfo.RedirectStandardOutput = true;
            proc1.StartInfo.RedirectStandardInput = true;
            //proc1.StartInfo.CreateNoWindow = true;
            string str1 = "";
            proc1.Start();

            str1 = proc1.StandardOutput.ReadToEnd();
            Thread.Sleep(1000);
            //proc1.Close();
            

            proc.StartInfo.Arguments += '"';
            proc.StartInfo.Arguments += Path.Combine(cgiFile.Replace(Path.GetFileName(cgiFile), ""), name + ".gex");
            proc.StartInfo.Arguments += '"';
            proc.StartInfo.Arguments += " ";
            proc.StartInfo.Arguments += "-gex";



            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.CreateNoWindow = true;
            //proc.Start();
            string str = "";
            proc.Start();

            str = proc.StandardOutput.ReadToEnd();
            proc.Close();
            proc.Dispose();
            File.Delete(Path.Combine(cgiFile.Replace(Path.GetFileName(cgiFile), ""), name + ".gex"));
            return str;
        }










        private string GetPythonData(string cgiFile)
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            string ext = Path.GetExtension(cgiFile);
            //indicate the executable to get stdout
            if (ext == "py" || ext == ".py" || ext == "pyw" || ext == ".pyw")
            {
                //proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "php", "php-cgi.exe");
                proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "python", "python.exe");
                //if path to the php is not defined
                if (!File.Exists(proc.StartInfo.FileName))
                {
                    string sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\MissingPy.htm"));
                    //SendHeader(sHttpVersion, "", sErrorMessage.Length,
                    //           " 404 Not Found", ref mySocket);
                    //(sErrorMessage, ref mySocket);
                    return sErrorMessage;

                    //SendLog(sFormattedMessage);
                }
                //proc.StartInfo.Arguments =   /*" -q " + */cgiFile + " " + QUERY_STRING;
                proc.StartInfo.Arguments += '"';
                proc.StartInfo.Arguments += cgiFile;
                proc.StartInfo.Arguments += '"';

            }
            else if (ext == "pyc" || ext == ".pyc" || ext == "pyo" || ext == ".pyo")
            {
                //proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "php", "php-cgi.exe");
                proc.StartInfo.FileName = Path.Combine(Application.StartupPath, "python", "pythonw.exe");
                //if path to the php is not defined
                if (!File.Exists(proc.StartInfo.FileName))
                {
                    string sErrorMessage = File.ReadAllText(Path.Combine(Application.StartupPath, @"pages\errors\MissingPy.htm"));
                    //SendHeader(sHttpVersion, "", sErrorMessage.Length,
                    //           " 404 Not Found", ref mySocket);
                    //(sErrorMessage, ref mySocket);
                    return sErrorMessage;

                    //SendLog(sFormattedMessage);
                }
                //proc.StartInfo.Arguments =   /*" -q " + */cgiFile + " " + QUERY_STRING;
                proc.StartInfo.Arguments += '"';
                proc.StartInfo.Arguments += cgiFile;
                proc.StartInfo.Arguments += '"';

            }
            
            string script_name = cgiFile.Substring(cgiFile.LastIndexOf('\\') + 1);
            //Set some global variables and output parameters
            
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.CreateNoWindow = true;
            string str = "";
            proc.Start();

            str = proc.StandardOutput.ReadToEnd();
            proc.Close();
            proc.Dispose();
            return str;
        }

        public string GetListing(string directory)
        {
            if (Directory.Exists(directory))
            {
                string code = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n";
                code += "<html>\n";
                code += "<head>\n";
                code += "<title>Index of " + Path.GetFullPath(directory).Replace(Program.WWWRoot, "").Replace('\\', '/') + "</title>\n";
                code += "</head>\n";
                code += "<body style=\"font-family: Verdana;\">\n";
                code += "<table style=\"border: 1px solid #C0C0C0; font-size: small; width: 100%;\">\n";
                code += "<thead>\n";
                code += "<tr><th style=\"width: 60%;\">Filename</th><th>Size</td><th style=\"width: 188px;\">Last modified on</th><th style=\"\">File type</th></tr>\n";
                code += "</thead>\n";
                code += "<tbody>\n";
                code += "<tr><td><a href=\"../\">..</a></td></tr>";
                if (Directory.GetFileSystemEntries(directory).Length == 0)
                {
                    code += "<td><b>Directory is empty!</b></td>";
                }
                else
                {
                    foreach (string f in Directory.GetFileSystemEntries(directory))
                    {
                        if ((File.GetAttributes(f) & FileAttributes.Directory) == FileAttributes.Directory)
                        {
                            code += "<tr>";
                            code += "<td>";
                            code += "<a href=\"" + Path.GetDirectoryName(f) + "/" + "\">" + Path.GetDirectoryName(f) + "</a></td>";
                            // get IEnumerable from all files in the current dir and all sub dirs
                            var files = Directory.EnumerateFiles(f, "*", SearchOption.AllDirectories);
                            // get the size of all files
                            long sum = 0;
                            foreach (string s in files)
                            {
                                FileInfo fli = new FileInfo(s);
                                sum += fli.Length;
                            }
                            decimal fgx = sum;
                            string unity = "B";

                            if (fgx > 1023)
                            {
                                unity = "KB";
                                fgx = fgx / 1024;
                                if (fgx > 1048575)
                                {
                                    unity = "MB";
                                    fgx = fgx / 1024;
                                    if (fgx > 1073741823)
                                    {
                                        unity = "GB";
                                        fgx = fgx / 1024;
                                        if (fgx > 1099511627775)
                                        {
                                            unity = "TB";
                                            fgx = fgx / 1024;
                                        }
                                    }
                                }
                            }
                            fgx = Math.Round(fgx, 1);
                            code += "<td>" + fgx + " " + unity + "</td>";

                            code += "<td></td>";
                            code += "<td>Folder</td>";

                        }
                        else
                        {
                            code += "<tr>";
                            code += "<td>";
                            code += "<a href=\"" + Path.GetFileName(f) + "\">" + Path.GetFileName(f) + "</a></td>";

                            FileInfo fli = new FileInfo(f);
                            
                            long sum = fli.Length;
                           
                            decimal fgx = sum;
                            string unity = "B";
                            if (fgx > 1023)
                            {
                                unity = "KB";
                                fgx = fgx / 1024;
                                if (fgx > 1048575)
                                {
                                    unity = "MB";
                                    fgx = fgx / 1024;
                                    if (fgx > 1073741823)
                                    {
                                        unity = "GB";
                                        fgx = fgx / 1024;
                                        if (fgx > 1099511627775)
                                        {
                                            unity = "TB";
                                            fgx = fgx / 1024;
                                        }
                                    }
                                }
                            }
                            fgx = Math.Round(fgx, 1);
                            code += "<td>" + fgx + " " + unity + "</td>";


                            //date
                            var xrt = File.GetLastWriteTime(f);
                            code += "<td>" + xrt.Day + " " + xrt.ToString("MMM", CultureInfo.InvariantCulture) + " " + xrt.Year + "</td>";



                            //type
                            SHFILEINFO info = new SHFILEINFO();
                            int cbFileInfo = Marshal.SizeOf(info);
                            SHGFI flags;
                            flags = SHGFI.TypeName | SHGFI.UseFileAttributes;
                            SHGetFileInfo(f, 256, out info, (uint)cbFileInfo, flags);
                            code += "<td>" + info.szTypeName + "</td>";
                        }
                    }
                }
                code += "</tbody>\n</table>\n<hr />\n<address>Xtreme Web Server 0.1</address>\n</body>\n</html>";
                return code;
            }
            else
            {
                return "";
            }
        }

        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, SHGFI uFlags);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public int iIcon;
            public uint dwAttributes;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };
        [Flags]
        public enum SHGFI : int
        {
            /// <summary>get icon</summary>
            Icon = 0x000000100,
            /// <summary>get display name</summary>
            DisplayName = 0x000000200,
            /// <summary>get type name</summary>
            TypeName = 0x000000400,
            /// <summary>get attributes</summary>
            Attributes = 0x000000800,
            /// <summary>get icon location</summary>
            IconLocation = 0x000001000,
            /// <summary>return exe type</summary>
            ExeType = 0x000002000,
            /// <summary>get system icon index</summary>
            SysIconIndex = 0x000004000,
            /// <summary>put a link overlay on icon</summary>
            LinkOverlay = 0x000008000,
            /// <summary>show icon in selected state</summary>
            Selected = 0x000010000,
            /// <summary>get only specified attributes</summary>
            Attr_Specified = 0x000020000,
            /// <summary>get large icon</summary>
            LargeIcon = 0x000000000,
            /// <summary>get small icon</summary>
            SmallIcon = 0x000000001,
            /// <summary>get open icon</summary>
            OpenIcon = 0x000000002,
            /// <summary>get shell size icon</summary>
            ShellIconSize = 0x000000004,
            /// <summary>pszPath is a pidl</summary>
            PIDL = 0x000000008,
            /// <summary>use passed dwFileAttribute</summary>
            UseFileAttributes = 0x000000010,
            /// <summary>apply the appropriate overlays</summary>
            AddOverlays = 0x000000020,
            /// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
            OverlayIndex = 0x000000040,
        }   
    }

}
